package top.wbhzx.wangpan.auth;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import top.wbhzx.wangpan.config.Constant;
import top.wbhzx.wangpan.service.UserService;
import top.wbhzx.wangpan.util.ServiceResult;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * @Author: JiangZuoWei,WangZhiXian
 * @Description: 权限过滤器
 * @Date: Create in 19:08 2019-05-27
 */
public class AuthFilter implements Filter {
    public static final String REQ_ATTR_TOKEN = "token_user_info";

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    private AuthService authService;

    private AuthConfig authConfig;

    @Autowired
    private UserService userService;

    public AuthService getAuthService() {
        return authService;
    }

    public void setAuthService(AuthService authService) {
        this.authService = authService;
    }

    public AuthConfig getAuthConfig() {
        return authConfig;
    }

    public void setAuthConfig(AuthConfig authConfig) {
        this.authConfig = authConfig;
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.debug("AuthFilter初始化");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        if (log.isDebugEnabled()) {
            log.debug("url:{} 被TokenAuthenticationFilter拦截检查", httpRequest.getRequestURI());
        }
        String requestPath = httpRequest.getRequestURI();
        String contextPath = httpRequest.getContextPath();
        String servletPath = httpRequest.getServletPath();
        // 如果工程路径没有就是/  ，所以这里把/去掉
        if (StringUtils.isNotBlank(contextPath)) {
            requestPath = requestPath.replace(contextPath, "");
        }
        if (hasIgnoreUrl(requestPath)) {
            log.info("忽略地址地址：{}",requestPath);
            filterChain.doFilter(request, response);
        } else {
            log.info("拦截请求地址：{}",requestPath);
            String token = httpRequest.getHeader("Authorization");
            if (StringUtils.isNotBlank(token)) {
                UserInfo userInfo = authService.getUserInfo(token);
                if (userInfo != null) {
                    request.setAttribute(REQ_ATTR_TOKEN, userInfo);
                    filterChain.doFilter(request, response);

                    //设置更新redis key 过期时间
                    authService.expireKey(token);
                    return;
                }
            }
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.setCharacterEncoding("UTF-8");
            httpResponse.setContentType("application/json; charset=utf-8");
            httpResponse.setStatus(HttpServletResponse.SC_OK);
            httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
            String originHeader = httpRequest.getHeader("Origin");
            httpResponse.setHeader("Access-Control-Allow-Origin", originHeader);
            httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT,HEAD");
            httpResponse.setHeader("Access-Control-Allow-Headers", "x-requested-with,content-type,Authorization");
            ObjectMapper mapper = new ObjectMapper();
            ServiceResult<Object> failure = ServiceResult.failure(Constant.ERROR_RETURN_CODE, "401,认证失败");
            httpResponse.getWriter().write(mapper.writeValueAsString(failure));
        }
    }

    /**
     * 检查url是否为被忽略的url
     * @param url
     * @return
     */
    private boolean hasIgnoreUrl(String url) {
        List<String> ignoreUrls = authConfig.getIgnoreUrls();
        if (null != ignoreUrls && !ignoreUrls.isEmpty()) {
            for (String ignoreUrl : ignoreUrls) {
                if (StringUtils.isNotBlank(ignoreUrl)
                        && ignoreUrl.equals(url)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public void destroy() {
        log.debug("AuthFilter销毁");
    }
}
